﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace BeginInvokeEndInvoke
{
    class Program
    {
        public class Person
        {
            public string Name;
            public int Age;
        }

        delegate string MyDelegate(string name);

        static void Main(string[] args)
        {
            ThreadMessage("Main Thread");

            MyDelegate myDelegate = new MyDelegate(Hello);

            Person person = new Person();
            person.Name = "Felix";
            person.Age = 29;

            myDelegate.BeginInvoke("Felix", new AsyncCallback(Completed), person);

            for (int n = 0; n < 6; n++)
            {
                Thread.Sleep(200);
                Console.WriteLine(" Main thread do work!");
            }
            Console.WriteLine("");


            Console.ReadKey();
        }

        static string Hello(string name)
        {
            ThreadMessage("Async Thread");
            Thread.Sleep(5000);
            return "Hello " + name;
        }

        static void Completed(IAsyncResult result)
        {
            ThreadMessage("Async Completed");

            AsyncResult _result = (AsyncResult)result;
            MyDelegate myDelegate = (MyDelegate)_result.AsyncDelegate;
            string data = myDelegate.EndInvoke(_result);

            Person person = (Person)result.AsyncState;
            string message = person.Name + "'s age is" + person.Age.ToString();

            Console.WriteLine(data + "\n" + message);
        }

        static void ThreadMessage(string data)
        {
            string message = string.Format("{0}\n   ThreadId is:{1}",
                data, Thread.CurrentThread.ManagedThreadId);
            Console.WriteLine(message);
        }
    }
}
